/*
Copyright (C) 2022-2024 Inspur Corp. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/
package service

import (
	"did-service/bean/entity"
	"did-service/bean/model"
	"did-service/bean/param"
	"did-service/common/constant"
	"did-service/common/db"
	"strconv"
	"time"
)

// 连查
type credentialGrantDidEntity struct {
	entity.CredentialGrant      `xorm:"extends"`
	entity.DidDocument          `xorm:"extends"`
	entity.VerifiableCredential `xorm:"extends"`
	entity.AuthorityIssuer      `xorm:"extends"`
	entity.CredentialCpt        `xorm:"extends"`
}

func (srv *DidService) ListCredentialToMe(para *param.ListGrantCredentialParam) (*db.Page, error) {
	condition := ""
	args := make([]interface{}, 0)
	list := make([]*credentialGrantDidEntity, 0)
	var enti credentialGrantDidEntity

	pageSize := 5
	if para.PageSize != "" {
		if size, err := strconv.Atoi(para.PageSize); err == nil {
			pageSize = size
		}
	}
	pageNum := 1
	if para.PageNum != "" {
		if num, err := strconv.Atoi(para.PageNum); err == nil {
			pageNum = num
		}
	}
	page := db.NewPage(0, pageNum).SetPageSize(pageSize)

	session := srv.engine.Table("credential_grant").Alias("a").
		Join("LEFT", []string{"did_document", "b"}, "a.grantee=b.did").
		Join("LEFT", []string{"verifiable_credential", "c"}, "a.object_id=c.id").
		Join("LEFT", []string{"authority_issuer", "d"}, "c.issuer_id=d.id").
		Join("LEFT", []string{"credential_cpt", "e"}, "c.cpt_id=e.id")
	combineSql(" b.wallet_id = ? and c.status = '1' ", &condition, para.WalletId, &args)
	combineSql(" and a.expiration_date > ?", &condition, time.Now().Format(constant.TimeLayout), &args)
	if para.IssuerName != "" {
		combineSql(" and d.name like '%"+para.IssuerName+"%' ", &condition, "", nil)
	}
	if para.CredentialName != "" {
		combineSql(" and e.title like '%"+para.CredentialName+"%' ", &condition, "", nil)
	}
	total, err := session.Where(condition, args...).Count(&enti)
	if err != nil {
		log.Errorf("list credentil grant to me error: %v", err)
		return nil, err
	}

	session = srv.engine.Table("credential_grant").Alias("a").
		Join("LEFT", []string{"did_document", "b"}, "a.grantee=b.did").
		Join("LEFT", []string{"verifiable_credential", "c"}, "a.object_id=c.id").
		Join("LEFT", []string{"authority_issuer", "d"}, "c.issuer_id=d.id").
		Join("LEFT", []string{"credential_cpt", "e"}, "c.cpt_id=e.id")
	err = session.Where(condition, args...).Limit(pageSize, (pageNum-1)*pageSize).Desc("a.updated_time").Find(&list)
	if err != nil {
		log.Errorf("list credentil grant to me error: %v", err)
		return nil, err
	}

	credentialList := make([]*model.GrantInfo, 0)
	for _, res := range list {
		credentialList = append(credentialList, &model.GrantInfo{
			CredentialId:   res.VerifiableCredential.Id,
			OwnerId:        res.CredentialGrant.OwnerId,
			OwnerDid:       res.CredentialGrant.OwnerDid,
			Grantee:        res.CredentialGrant.Grantee,
			CredentialName: res.Title,
			IssuerName:     res.Name,
			GrantDate:      res.GrantDate.Format(constant.TimeLayout),
			ExpirationDate: res.CredentialGrant.ExpirationDate.Format(constant.TimeLayout),
		})
	}
	page.SetTotal(total)
	page.CreatePage(credentialList)
	return page, nil
}

func (srv *DidService) ListCredentialToOther(para *param.ListGrantCredentialParam) (*db.Page, error) {
	condition := ""
	args := make([]interface{}, 0)
	list := make([]*credentialGrantDidEntity, 0)
	var enti credentialGrantDidEntity

	pageSize := 5
	if para.PageSize != "" {
		if size, err := strconv.Atoi(para.PageSize); err == nil {
			pageSize = size
		}
	}
	pageNum := 1
	if para.PageNum != "" {
		if num, err := strconv.Atoi(para.PageNum); err == nil {
			pageNum = num
		}
	}
	page := db.NewPage(0, pageNum).SetPageSize(pageSize)

	session := srv.engine.Table("credential_grant").Alias("a").
		Join("LEFT", []string{"did_document", "b"}, "a.owner_id=b.wallet_id and a.owner_did=b.did").
		Join("LEFT", []string{"verifiable_credential", "c"}, "a.object_id=c.id").
		Join("LEFT", []string{"authority_issuer", "d"}, "c.issuer_id=d.id").
		Join("LEFT", []string{"credential_cpt", "e"}, "c.cpt_id=e.id")
	combineSql(" a.owner_id = ? and c.status = '1' ", &condition, para.WalletId, &args)
	combineSql(" and a.expiration_date > ? ", &condition, time.Now().Format(constant.TimeLayout), &args)
	if para.IssuerName != "" {
		combineSql(" and d.name like '%"+para.IssuerName+"%' ", &condition, "", nil)
	}
	if para.CredentialName != "" {
		combineSql(" and e.title like '%"+para.CredentialName+"%' ", &condition, "", nil)
	}
	total, err := session.Where(condition, args...).Count(&enti)
	if err != nil {
		log.Errorf("list credentil grant to me error: %v", err)
		return nil, err
	}

	session = srv.engine.Table("credential_grant").Alias("a").
		Join("LEFT", []string{"did_document", "b"}, "a.owner_id =b.wallet_id and a.owner_did=b.did").
		Join("LEFT", []string{"verifiable_credential", "c"}, "a.object_id=c.id").
		Join("LEFT", []string{"authority_issuer", "d"}, "c.issuer_id=d.id").
		Join("LEFT", []string{"credential_cpt", "e"}, "c.cpt_id=e.id")
	err = session.Where(condition, args...).Limit(pageSize, (pageNum-1)*pageSize).Desc("a.updated_time").Find(&list)
	if err != nil {
		log.Errorf("list credentil grant to me error: %v", err)
		return nil, err
	}

	credentialList := make([]*model.GrantInfo, 0)
	for _, res := range list {
		credentialList = append(credentialList, &model.GrantInfo{
			CredentialId:   res.VerifiableCredential.Id,
			OwnerId:        res.CredentialGrant.OwnerId,
			OwnerDid:       res.CredentialGrant.OwnerDid,
			Grantee:        res.CredentialGrant.Grantee,
			CredentialName: res.Title,
			IssuerName:     res.Name,
			GrantDate:      res.GrantDate.Format(constant.TimeLayout),
			ExpirationDate: res.CredentialGrant.ExpirationDate.Format(constant.TimeLayout),
		})
	}
	page.SetTotal(total)
	page.CreatePage(credentialList)
	return page, nil
}
